#include "QQEmojiDelegate.h"

QQEmojiDelegate::QQEmojiDelegate(QObject* parent)
	: QStyledItemDelegate(parent)
{
	mItemSize = QSize(50, 50);
	mFrameTimer = new QTimer(this);
	mFrameTimer->setInterval(1000 / 30);
	mCurrentFrame = 0;
	mTotalFrames = 0;
	connect(mFrameTimer, &QTimer::timeout, this, &QQEmojiDelegate::onFrameTimeout);
}

QQEmojiDelegate::~QQEmojiDelegate()
{
}

void QQEmojiDelegate::setItemSize(QSize size)
{
	mItemSize = size;
}

QSize QQEmojiDelegate::getItemSize() const
{
	return mItemSize;
}

void QQEmojiDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QQChatEmoji* emoji = index.data(Qt::UserRole).value<QQChatEmoji*>();
	QQEmojiModel* model = const_cast<QQEmojiModel*>(static_cast<const QQEmojiModel*>(index.model()));
	QRect rect = option.rect.adjusted(1, 1, -1, -1);
	painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
	if (option.state & QStyle::State_Sunken)
	{
		QPainterPath path;
		path.addRoundedRect(rect, 10, 10);
		painter->fillPath(path, Qt::gray);
	}
	else if (option.state & QStyle::State_MouseOver)
	{
		QPainterPath path;
		path.addRoundedRect(rect, 10, 10);
		painter->fillPath(path, Qt::blue);
	}
	else
	{
		if (mFrameTimer->isActive())
		{
			mFrameTimer->stop();
			mCurrentFrame = 0;
		}
	}
	switch (emoji->type)
	{
	case QQEmojiType::Picture:
	{
		painter->drawImage(rect, QImage(emoji->path));
		break;
	}
	case QQEmojiType::Gif:
	{
		QImage image = QImage(emoji->preview);
		if (mFrameTimer->isActive())
			image = model->getMovieFrame(emoji->id, mCurrentFrame, rect.width(), rect.height());
		painter->drawImage(rect, image);
		break;
	}
	case QQEmojiType::Lottie:
	{
		QImage image = QImage(emoji->preview);
		if (mFrameTimer->isActive())
			image = model->getLottieFrame(emoji->id, mCurrentFrame, rect.width(), rect.height());
		painter->drawImage(rect, image);
		break;
	}
	default:
		break;
	}
}

QSize QQEmojiDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	return mItemSize;
}

bool QQEmojiDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
	QQChatEmoji* emoji = index.data(Qt::UserRole).value<QQChatEmoji*>();
	if (emoji->type == QQEmojiType::Picture)
		return QStyledItemDelegate::editorEvent(event, model, option, index);
	switch (event->type())
	{
	case QEvent::MouseMove:
	{
		const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
		if (option.rect.contains(mouseEvent->pos()))
		{
			if (mPersistIndex != index)
			{
				mPersistIndex = QPersistentModelIndex(index);
				mCurrentFrame = 0;
				switch (emoji->type)
				{
				case QQEmojiType::Gif:
				{
					mTotalFrames = const_cast<QQEmojiModel*>(static_cast<const QQEmojiModel*>(model))->getMovieFrameCount(emoji->id);
					break;
				}
				case QQEmojiType::Lottie:
				{
					mTotalFrames = const_cast<QQEmojiModel*>(static_cast<const QQEmojiModel*>(model))->getLottieFrameCount(emoji->id);
					break;
				}
				default:
					break;
				}
			}
			if (!mFrameTimer->isActive())
			{
				mCurrentFrame = 0;
				mFrameTimer->start();
			}
		}
		break;
	}
	default:
		break;
	}
	return QStyledItemDelegate::editorEvent(event, model, option, index);
}

void QQEmojiDelegate::onFrameTimeout()
{
	if (mPersistIndex.isValid())
	{
		mCurrentFrame = (mCurrentFrame + 1) % mTotalFrames;
		emit const_cast<QAbstractItemModel*>(qobject_cast<const QAbstractItemModel*>(mPersistIndex.model()))->dataChanged(mPersistIndex, mPersistIndex);
	}
}
